/*
 * redmicro all Copyright (c)
 *
 * Created by seeker910 on 14-3-17.
 * JsonSchema对象
 * 应用场景：
 * 1、
 */
Rsd.define('Rsd.data.JsonSchema', {
    extend:'Rsd.common.Object',
    xtype:'json-schema',
    allFields:
    [
        {
            name:"$id",
            text:'键值',
        }, 
        {
            name:"type",
            text:"数据类型"
        }, 
        {
            //非标准属性
            name:"xtype",
            text:"编辑控件类型" 
        }, 
        {
            //redjs额外增加属性
            name:'for',
            text:"适用对象",//"","all","xxxx";空或all表示 适配所有属性； xxxx 表示 只适配xxxx指定的属性
        },
        {
            name:'viewTemplate',
            text:'该schema支持适配的视图模板集合'//{tpl1:{},tpl2:{}}
        },
        {name:"$ref",text:"引用"},
        //$defs
        {name:"dependencies",text:"依赖"},
        //数据类型
        {name:"title",text:'数据源名称'},
        {name:"default",text:"默认值"},
        {name:"description",text:"数据描述"},
        {name:"examples",text:"示例数据"},
       
        //"readonly" 
        //"writeOnly"
     
        //string
        {name:"minLength",text:"最小长度","for":"string"},
        {name:"maxLength",text:"最大长度","for":"string"},
        {name:"pattern",text:"正则表达式","for":"string"},
        {name:"format",text:"格式化表达式","for":"string"}, 
        {name:"enum",text:"枚举","for":"string"}, 

        //number
        {name:"multipleOf",text:"是该值的倍数","for":"number"},
        {name:"maximum",text:"最大值","for":"number"},
        {name:"exclusiveMaximum",text:"不包含最大值","for":"number"},
        {name:"minimum",text:"最小值","for":"number"},
        {name:"exclusiveMinimum",text:"不包含最小值","for":"number"},
       
         //对象类型 约束
        //{name:"properties",text:"属性","for":"object"},
        //patternProperties 属性名通过正则表达式匹配
        {name:"additionalProperties",text:"其他属性Schema","for":"object"},
        {name:"minProperties",text:"最少属性成员","for":"object"},
        {name:"maxProperties",text:"最多属性成员","for":"object"},
        {name:"required",text:"必填属性","for":"object"}, 

        //数组类型 约束
        //{name:"items",text:"数组元素Schema","for":"array"},
        {name:"additionalItems",text:"其他数组元素Schema","for":"array"},
        {name:"minItems",text:"数组最小长度","for":"array"},
        {name:"maxItems",text:"数组最大长度","for":"array"},
        {name:"uniqueItems",text:"数组中元素唯一","for":"array"},

        //结合类型 子元素约束
        {name:"allOf",text:"必须满所有子Schema"},
        {name:"anyOf",text:"满足其中一个或多个子Schema"},
        {name:"oneOf",text:"满足其中一个子Schema"},
        {name:"not",text:"不允许满足的子Schema"}
    ],
    /**示例数据 */
    data:null,
    /**
     * 属性
     */
    properties:{},
    /**
     * @description 该属性为redjs额外增加属性,"","all","xxxx";
     * @description 空或all表示 适配所有属性； xxxx 表示 只适配该控件指定的属性xxxx
     */
    for:'',
    /**
     * 
     */
    constructor: function JsonSchema (config) {
        config = config || {};
        this.apply(config);
    },
    /**
     * @description 根据schema 从对象中 获取data
     * @param {*} obj 
     * @param {*} forTpl 数据适配模板 
     */
    getData:function getData(obj)
    {
        //console.log(obj); 
        //console.log(this.properties);

        var data = {};
        if(!Rsd.isEmpty(this.for) && this.for.toLowerCase() != 'all')
        {  
            data[this.for] = obj[this.for]; 
        }
        else
        {
            for(var p in this.properties)
            {  
                 var _p_schema = this.properties[p];
                //console.log('schema p is ',p,this.properties[p].type,obj[p]);
                switch(_p_schema.type)
                {
                    case 'object': 
                        { 
                            if(obj[p])
                            { 
                                //console.log('object schema',obj[p].schema);
                                var _schema = new Rsd.data.JsonSchema(_p_schema);
                                data[p] = _schema.getData(obj[p]);  
                            }
                            else
                            {
                                data[p] = {};
                            } 
                            break;
                        } 
                    case 'array':
                        {
                            //console.log('array schema items',obj.xtype,obj.items);
                            data[p]=[];
                            if(_p_schema.items.oneOf)
                            {
                                for(var i in obj.items)
                                { 
                                    if(obj.items[i].schema)
                                    {
                                        data[p].push(obj.items[i].schema.getData(obj.items[i]));
                                    }
                                    else
                                    {
                                        console.log('item object is not schema ',obj.items[i]);
                                    }
                                    
                                }  
                            }
                            else
                            {
                                var _schema = new Rsd.data.JsonSchema(_p_schema.items);
                                for(var i in obj.items)
                                {
                                    data[p].push(_schema.getData(obj.items[i]));
                                    //listItemEditView:是试图展示模板名称，在jsonSchema 定义时，在viewTemplate 属性中定义模板 
                                }
                            }
                              
                            break;
                        } 
                    default:
                        data[p] = obj[p]; 
                        break;
                }
                
            }
        }

        if(obj instanceof Rsd.common.ComponentX)
        {
            if(obj['key'] !== undefined && obj['key'] !== null)
            {
                data['key'] = obj['key'];
            }
            if(obj['id'] !== undefined && obj['id'] !== null)
            {
                data['id'] = obj['id'];
            }
            
            if(obj['style'])
            {
                data['style'] = obj['style'];
            }
            if(obj['height'])
            {
                data['height'] = obj['height'];
            }
            if(obj['width'])
            {
                data['width'] = obj['width'];
            }
            if(obj['margin'])
            {
                data['margin'] = obj['margin'];
            }
            if(obj['layout'])
            {
                data['layout'] = obj['layout'];
            }
            if(obj['flex'])
            {
                data['flex'] = obj['flex'];
            }
            if(obj['xtype'])
            {
                data['xtype'] = obj['xtype'];
            }
            //label 
            //不能允许设置，如果需要修改，可以通过定义dataSource来实现修改
            if(obj['label'] && obj['label'].visible == false)
            {
                data['label']=false;
            }
            //header
            //不能允许设置，如果需要修改，可以通过定义dataSource来实现修改
            if(obj['header'] && obj['header'].visible == false)
            {
                data['header']=false;
            }
        } 
        return data;
    },
    /**
     * 获取数据并根据指定的模板名称，将数据通过模板渲染后输出
     * @param {*} obj 
     * @param {*} forTpl 适配 视图 模板名称,
     * @returns 
     */
    getViewData:function getViewData(obj,forTpl)
    {
        //console.trace(arguments);
         var data = {};
         if(obj === undefined || obj === null)
         {
            return data;
         }
         if(!Rsd.isObject(obj))
         {
            console.error('The value of argument obj must be object type. current value is',obj);
            return data;
         }
         //console.log('obj  is:',obj);
        if(!Rsd.isEmpty(this.for) && this.for.toLowerCase() != 'all')
        {
            data[this.for] = obj[this.for];
        }
        else
        {
            for(var p in this.properties)
            {  
                //console.log('schema p is ',p,this.properties[p].type,obj[p]);
                var _p_schema = this.properties[p];
                switch(_p_schema.type)
                {
                    case 'object': 
                        { 
                            if(obj[p])
                            {  
                                //console.log('object schema',_p_schema);
                                var _schema = new Rsd.data.JsonSchema(_p_schema);
                                data[p] = _schema.getViewData(obj[p],forTpl||'');  
                            }
                            else
                            {
                                data[p] = {};
                            } 
                            break;
                        } 
                    case 'array':
                        {
                            //console.log('array schema items',obj.xtype,obj.items,_p_schema);
                            data[p]=[];
                            if(_p_schema.items.oneOf)
                            {
                                //数组元素 是异构 的
                                for(var i in obj.items)
                                {  
                                    //console.log('array item(id:'+obj.items[i].id+')',obj.items[i]);
                                    data[p].push(obj.items[i].schema.getViewData(obj.items[i],forTpl||'listItemEditView'));
                                }  
                            }
                            else
                            {
                                var _schema = new Rsd.data.JsonSchema(_p_schema.items);
                                for(var i in obj.items)
                                {
                                    data[p].push(_schema.getViewData(obj.items[i],forTpl||'listItemEditView'));
                                    //listItemEditView:是视图展示模板名称，在jsonSchema 定义时，在viewTemplate 属性中定义模板 
                                }
                            }
                              
                            break;
                        } 
                    default:
                        data[p] = obj[p]; 
                        break;
                }
                
            }
        }
        //console.log(obj);
        if(obj['key'] !== undefined && obj['key'] !== null)
        {
            data['key'] = obj['key'];
        }
        if(obj['id'] !== undefined && obj['id'] !== null)
        {
            data['id'] = obj['id'];
        }
        //console.log(forTpl,this.viewTemplate);
        //list item 模板 数据 适配
        if(forTpl && this.viewTemplate && this.viewTemplate[forTpl]) 
        { 
            var tpl = this.viewTemplate[forTpl]; 
            tpl.xtype =  tpl.xtype ||'json-form';
            data = Rsd.template(tpl,data);
            data['forTpl'] = forTpl;//标识 viewTemplate 名称

            //console.log('get object （'+(obj.id||'-')+'） view data',obj,data,JSON.stringify(data),this);
        }
        
        return data;
    },
    /**
     * @description 根据schema 将data 设置到obj对应属性上
     * @param {*} obj 
     */
    setData:function setData(obj,data)
    {
        if(!Rsd.isEmpty(this.for) && this.for.toLowerCase() != 'all')
        {
              obj[this.for] = data[this.for]; 
              return;
        }

        for(var p in this.properties)
            {  
                //console.log('schema p is ',p,this.properties[p].type,obj[p]);
                switch(this.properties[p].type)
                {
                    case 'object': 
                        { 
                            if(data[p])
                            {  
                                var _schema = new Rsd.data.JsonSchema(obj[p].schema);
                                _schema.setData(obj[p],data[p]);  
                            }
                            else
                            {
                                obj[p] = {};
                            } 
                            break;
                        } 
                    case 'array':
                        {  
                            for(var i in obj.items)
                            { 
                                 obj[p] = data[p]; 
                            }    
                            break;
                        } 
                    default:
                        obj[p] = data[p]; 
                        break;
                }
                
            }
    },
    /**
     * 
     * @param {*} name 
     * @returns 
     */
    getProperty:function getProperty(name)
    {
        var p = this.properties[name];
        if(p)
        {
            return new Rsd.data.JsonSchema(p);
        }
    }

});
